package com.sbpm.crmbpm.server.mgmt.impl;

/*
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sample.gxt.client.GreetingService;
import com.sample.gxt.client.ProcessService;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.servlet.annotation.WebServlet;
*/

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sbpm.crmbpm.client.services.ProcessService;
import com.sbpm.crmbpm.server.dao.ObjectConverter;
import com.sbpm.crmbpm.shared.TransferEntity;
import com.sbpm.crmbpm.shared.data.InsuranceRequestInfo;
import com.sbpm.crmbpm.shared.data.TaskInfo;
import org.drools.core.command.impl.GenericCommand;
import org.drools.core.command.impl.KnowledgeCommandContext;
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.instance.context.variable.VariableScopeInstance;
import org.kie.api.runtime.KieSession;
import org.kie.api.task.TaskService;
import org.kie.api.task.model.Task;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.command.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//@WebServlet( name = "processService",  urlPatterns = {"/processService"} )
//@Service
public class ProcessServiceImpl extends RemoteServiceServlet implements
        ProcessService
{

    public static final String INSURANCE_REQUEST_PROCESS = "com.sbpm.isurance.InsuranceRequest";
    @Autowired
    private KieSession ksession;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ObjectConverter objectConverter;

    public Long createMoneyTransferProcessInstance() {

/*
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("priority", "High");
        params.put("modelNumber", "123");
        params.put("quantity", "66");
*/

        return ksession.startProcess( "com.bpm.sample.MoneyTransfer" ).getId();
    }

    public Long createInsuranceRequestProcessInstance()
    {
        return ksession.startProcess( INSURANCE_REQUEST_PROCESS ).getId();
    }


    public void setVariables( Long taskId, final Map< String, Object > variables )
    {
        final Long processInstanceId = taskService.getTaskById( taskId ).getTaskData().getProcessInstanceId();
        ksession.execute( new GenericCommand()
        {
            public Object execute( Context context )
            {

                KieSession ksession = ( ( KnowledgeCommandContext ) context ).getKieSession();
                org.jbpm.process.instance.ProcessInstance processInstance = ( org.jbpm.process.instance.ProcessInstance ) ksession.getProcessInstance( processInstanceId );
                VariableScopeInstance variableScope = ( VariableScopeInstance ) processInstance.getContextInstance( VariableScope.VARIABLE_SCOPE );
                for( Map.Entry< String, Object > entry : variables.entrySet() )
                {
                    variableScope.setVariable( entry.getKey(), entry.getValue() );
                }

                return null;

            }
        } );
    }

    public Map<String, Object> getTaskData( Long taskId )
    {

        final Long processInstanceId = taskService.getTaskById( taskId ).getTaskData().getProcessInstanceId();
        Map<String, Object> variables = ksession.execute(new GenericCommand<Map<String, Object>>() {

            public Map<String, Object> execute(Context context) {

                KieSession ksession = ((KnowledgeCommandContext ) context).getKieSession();
                org.jbpm.process.instance.ProcessInstance processInstance = (org.jbpm.process.instance.ProcessInstance) ksession.getProcessInstance(processInstanceId);
                VariableScopeInstance variableScope = (VariableScopeInstance ) processInstance.getContextInstance( VariableScope.VARIABLE_SCOPE);
                Map<String, Object> map = new HashMap< String, Object >();
                map.putAll( variableScope.getVariables() );
                return map;
                //return variables;

            }

        });
        return variables;//variables;//taskService.getTaskContent( taskId );

    }

    public String getTaskName( Long taskId )
    {
        Task task = taskService.getTaskById( taskId );
        return task.getName();
    }

    public Map<String, Object> startTask( Long taskId, String user )
    {
        Map<String, Object> data = getTaskData( taskId );
        taskService.start( taskId, user );
        return data;
    }

    public void stopTask( Long taskId, String user )
    {
        taskService.release( taskId, user );
    }

    public void completeTask( Long taskId, String user, Map<String, Object> data )
    {

        taskService.complete( taskId, user, data );
//        setVariables( taskId, data );
    }

    public void moveFlow( Long taskId, String user )
    {
        taskService.start( taskId, user );
        taskService.complete( taskId, user, new HashMap() );
    }

    public List<TaskInfo> getTaskList( String user )
    {
        List<TaskSummary> tasks = taskService.getTasksAssignedAsPotentialOwner(user, "en-UK");
        return objectConverter.convertTaskList( tasks );
    }

    /*private Map<String, Object> convertToInfo( Map<String, Object> data )
    {
        if( data.get( "transfer" ) != null )
        {
            //data.put( varName, objectConverter.convertTransfer( ( TransferEntity )data.get( varName ) ) );
            TransferEntity transfer = ( TransferEntity ) data.get( "transfer" );
            data.remove( "transfer" );
            data.put( "transfer.name", transfer.getName() );
            data.put( "transfer.receiver", transfer.getReceiver() );
            data.put( "transfer.sum", transfer.getSum() );
            data.put( "transfer.id", transfer.getId() );
            data.put( "transfer.processInstanceId", transfer.getProcessInstanceId() );
            data.remove( "transfer" );
        }

        return data;
    }*/

    private Map<String, Object> convertToInfo( Map<String, Object> data )
    {
        InsuranceRequestInfo info = new InsuranceRequestInfo();
        if( data.get( "transfer" ) != null )
        {
            //data.put( varName, objectConverter.convertTransfer( ( TransferEntity )data.get( varName ) ) );
            TransferEntity transfer = ( TransferEntity ) data.get( "transfer" );
            data.remove( "transfer" );
            data.put( "transfer.name", transfer.getName() );
            data.put( "transfer.receiver", transfer.getReceiver() );
            data.put( "transfer.sum", transfer.getSum() );
            data.put( "transfer.id", transfer.getId() );
            data.put( "transfer.processInstanceId", transfer.getProcessInstanceId() );
            data.remove( "transfer" );
        }

        return data;
    }

    private Map<String, Object> convertToEntity( Map<String, Object> data )
    {
        TransferEntity entity = new TransferEntity();
//        Map<String, Object> map = new HashMap<>();
        for( String varName : data.keySet() )
        {
            /*if( data.get( varName ) instanceof TransferInfo )
            {
                data.put( varName, objectConverter.convertTransfer( ( TransferInfo )data.get( varName ) ) );
            }*/
            switch( varName )
            {
                case "transfer.name":
                    entity.setName( ( String ) data.get( varName ) );
                    break;
                case "transfer.receiver":
                    entity.setReceiver( ( String ) data.get( varName ) );
                    break;
                case "transfer.sum":
                    entity.setSum( ( String ) data.get( varName ) );
                    break;
                case "transfer.id":
                    entity.setId( ( Long ) data.get( varName ) );
                    break;
                case "transfer.processInstanceId":
                    entity.setProcessInstanceId( ( Long ) data.get( varName ) );
                    break;
            }
        }
        data.put( "transfer", entity );
        data.remove( "transfer.name" );
        data.remove( "transfer.receiver" );
        data.remove( "transfer.sum" );
        data.remove( "transfer.id" );
        data.remove( "transfer.processInstanceId" );
        return data;
    }

    public void dummyDate( Date date, Boolean bool, BigDecimal bigDecimal )
    {

    }

    public Double dummyDouble( Double doub )
    {
        return 0D;
    }
    public BigDecimal dummyBigDecimal( BigDecimal bd )
    {
        return BigDecimal.ONE;
    }
}
